
#include "processmgr.h"
#include "util.h"
#include <otl.h>
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

NAMESPACE_BILLING40_FRAME_BEGIN

volatile bool g_bRun = false;

void sig_term(int32 iSigNo)
{
	if(g_pProcessMgr != NULL)
	{
		g_pProcessMgr->LogAppend(NAMESPACE_BILLING40_LOG INFO_LEVEL,
			"receive signal %d, stop program ...",
			iSigNo);
	}
	if(g_bRun)
	{
		g_bRun = false;
		NAMESPACE_BILLING40_FRAME CProcessMgr::m_iSignal = iSigNo;
	}
}

void sig_unprocess(int32 iSigNo)
{
	static AISTD map< int32, time_t > mapSigTime;
	time_t& tLastLogTime = mapSigTime[iSigNo];
	if(tLastLogTime + 4 > g_pTime->m_tmVal.tv_sec) return;

	g_pProcessMgr->LogAppend(NAMESPACE_BILLING40_LOG WARN_LEVEL,
		"receive unprocess signal %d",
		iSigNo);
	mapSigTime[iSigNo] = g_pTime->m_tmVal.tv_sec;
}

int32 set_signal(const int32& iSigNo, void (*disp)(int32))
{
	struct sigaction act;
	act.sa_handler=disp;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	return sigaction(iSigNo, &act, NULL);
}

int32 process_signal()
{
	int32 iRet = 0;
	sigset_t setSig;
	sigemptyset(&setSig);

	for(int32 i=1;i<32;++i)
	{
		switch(i)
		{
		case SIGINT:
		case SIGTERM:
			iRet = set_signal(i, sig_term);
			if(iRet != 0)
			{
				printf("set signal func err, sig %d, errno %d\n",
					i,
					errno);
				return iRet;
			}
			break;
		case SIGHUP:
		case SIGPIPE:
		case SIGALRM:
		case SIGUSR1:
		case SIGUSR2:
		case SIGPOLL:
		case SIGVTALRM:
		case SIGPROF:
		case SIGCONT:
			sigaddset(&setSig, i);
			break;
		case SIGKILL:
		case SIGSTOP:
		case SIGBUS:
		case SIGSEGV:
		case SIGABRT:
		case SIGSYS:
//		case SIGWAITING:
#ifdef AIXV5
		case EL3HLT:
#endif
			break;
#ifdef HPUX
		default:
			;
#else
		default:
			iRet = set_signal(i, sig_unprocess);
			if(iRet != 0)
			{
				printf("set signal func err, sig %d, errno %d\n",
					i,
					errno);
				return iRet;
			}
#endif
		}
	}
	iRet = sigprocmask(SIG_BLOCK, &setSig, NULL);
	if(iRet != 0)
	{
		printf("block signal err, errno %d\n",
			errno);
		return iRet;
	}
	return iRet;
}

void print_hint(const char *cszFileName)
{
	AISTD cout << "The usage: " << AISTD endl
	<< cszFileName << " <-<I,i>config_file> <-<H,h>>"
	<< AISTD endl
	<< "I is config file default is ./frame.cfg." << AISTD endl
	<< "H print hint and exit." << AISTD endl;
	return ;
}

const char *cszDefaultConfigFile = "./frame.xml";
char szConfigFile[512];

NAMESPACE_BILLING40_FRAME_END

int main(int argc, char *argv[])
{
	//the otl_connect must be initialized at the begining of the program at HP platform
	try
	{
		otl_connect::otl_initialize(1);
	}
	catch(const otl_exception& e)
	{
		printf(
			"otl initialize database error, %s, %s, %s",
			e.msg,
			e.stm_text,
			e.var_info);
		return -1;
	}
	printf("otl initialize\n");

	NAMESPACE_BILLING40_FRAME CProgParam::set_arg(argc, argv);
	int32 c = 0;
	bool bSetDaemon = false;
//	while ((c = getopt(argc, argv, "I:i:M:m:Hh")) != EOF)
	while((c = NAMESPACE_BILLING40_FRAME CProgParam::getopt("I:i:Hhm")) != EOF)
	{
		switch (c)
		{
		case 'I' :
		case 'i' :
		       	strcpy(NAMESPACE_BILLING40_FRAME szConfigFile, optarg);
			break;
		case 'm' :
			bSetDaemon = true;
			break;
		case 'H' :
		case 'h' :
		default  :
			;
//			NAMESPACE_BILLING40_FRAME print_hint(argv[0]);
//			return (1);
		}
	}

	if(*NAMESPACE_BILLING40_FRAME szConfigFile == '\0')
	{
		strcpy(NAMESPACE_BILLING40_FRAME szConfigFile, "./frame.xml");
	}

//	NAMESPACE_BILLING40_FRAME set_signal(SIGINT, NAMESPACE_BILLING40_FRAME sig_term);
//	NAMESPACE_BILLING40_FRAME set_signal(SIGTERM, NAMESPACE_BILLING40_FRAME sig_term);
//	NAMESPACE_BILLING40_FRAME set_signal(SIGPIPE, NAMESPACE_BILLING40_FRAME sig_pipe);
//	NAMESPACE_BILLING40_FRAME set_signal(SIGALRM, NAMESPACE_BILLING40_FRAME sig_pipe);

	int32 iRet = 0;

	iRet = NAMESPACE_BILLING40_FRAME process_signal();
	if(iRet != 0) return 0;

	//init xml lib
	iRet = NAMESPACE_BILLING40_XML_CONFIG CConfig::init_xmlLib();
	if(iRet!=0) return 0;

	g_pProcessMgr = new NAMESPACE_BILLING40_FRAME CProcessMgr();
	NAMESPACE_BILLING40_FRAME g_bRun = true;

	iRet = g_pProcessMgr->start(
		NAMESPACE_BILLING40_FRAME szConfigFile,
		argv[0],
		bSetDaemon);
	if(iRet < 0) return -1;

	while(NAMESPACE_BILLING40_FRAME g_bRun)
	{
		iRet = g_pProcessMgr->manage();
		if(iRet != 0) break;
	}

	g_pProcessMgr->stop();
	delete g_pProcessMgr;
	g_pProcessMgr = NULL;

	// And call the termination method
	NAMESPACE_BILLING40_XML_CONFIG CConfig::destroy_xlmLib();

	return 0;
}

